home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJSRC111.ZIP / go32 / stubedit.c < prev    next >
C/C++ Source or Header  |  1993-10-17  |  9KB  |  412 lines

  1. /* This is file STUBEDIT.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <io.h>
  19. #include <fcntl.h>
  20.  
  21. #include "gotypes.h"
  22. #include "stubinfo.h"
  23.  
  24. word32 offset_of_info = 0;
  25. word32 size_of_info = 0;
  26.  
  27. StubInfo stub_info = {
  28.   STUB_INFO_MAGIC
  29. };
  30.  
  31. char *key = stub_info.magic;
  32.  
  33. void find_info(char *filename)
  34. {  
  35.   FILE *f;
  36.   int ch, found = 0;
  37.   int key_p;
  38.   long key_max, key_cnt=0;
  39.   unsigned char header[6];
  40.   unsigned char test_magic[16];
  41.  
  42.   f = fopen(filename, "rb");
  43.   if (f == 0)
  44.   {
  45.     char buf[100];
  46.     sprintf(buf, "Fatal error in stubedit reading %s", filename);
  47.     perror(buf);
  48.     exit(1);
  49.   }
  50.  
  51.   fread(header, 6, 1, f);
  52.   key_max = header[4] + header[5]*256 + 1;
  53.   key_max *= 512;
  54.  
  55.   /* First, look for tag */
  56.   fseek(f, -4L, 2);
  57.   fread(test_magic, 4, 1, f);
  58.   offset_of_info = (test_magic[0])
  59.                  | (test_magic[1] << 8)
  60.                  | (test_magic[2] << 16)
  61.                  | (test_magic[3] << 24);
  62.   if (offset_of_info > 0 && offset_of_info < key_max)
  63.   {
  64.     fseek(f, offset_of_info, 0);
  65.     fread(test_magic, 16, 1, f);
  66.     if (strcmp((char *)test_magic, key) == 0)
  67.       found = 1;
  68.   }
  69.  
  70.   if (!found)
  71.   {
  72.     fseek(f, 0L, 0);
  73.     key_p = 0;
  74.     while ((ch = fgetc(f)) != EOF)
  75.     {
  76.       if (ch == key[key_p])
  77.       {
  78.         key_p++;
  79.         if (key[key_p] == 0)
  80.         {
  81.           fgetc(f); /* the NULL */
  82.           offset_of_info = ftell(f) - 16; /* skip the NULL in the file */
  83.           found = 1;
  84.           break;
  85.         }
  86.       }
  87.       else
  88.         key_p = 0;
  89.       key_cnt++;
  90.       if (key_cnt > key_max)
  91.         break;
  92.     }
  93.   }
  94.   if (!found)
  95.   {
  96.     fprintf(stderr, "Error: I cannot find the stub info structure.  Must be either\n");
  97.     fprintf(stderr, "this is not a stub'd program, or it is older and does not have one.\n");
  98.     exit(1);
  99.   }
  100.  
  101.   fseek(f, offset_of_info + 16L, 0);
  102.   fread(&size_of_info, 1, 4, f);
  103.   stub_info.struct_length = size_of_info;
  104.   if (size_of_info > sizeof(StubInfo))
  105.     size_of_info = sizeof(StubInfo);
  106.   fseek(f, offset_of_info, 0);
  107.   fread(&stub_info, 1, (int)size_of_info, f);
  108.   fclose(f);
  109.   return;
  110. }
  111.  
  112. void store_info(char *filename)
  113. {
  114.   FILE *f;
  115.   f = fopen(filename, "r+b");
  116.   if (f == 0)
  117.   {
  118.     char buf[100];
  119.     sprintf(buf, "Fatal error in stubedit writing %s", filename);
  120.     perror(buf);
  121.     exit(1);
  122.   }
  123.   fseek(f, offset_of_info, 0);
  124.   fwrite(&stub_info, 1, (int)size_of_info, f);
  125.   fclose(f);
  126. }
  127.  
  128. char *pose_question(char *question, char *default_answer)
  129. {
  130.   static char response[200];
  131.   printf("%s ? [%s] ", question, default_answer);
  132.   fflush(stdout);
  133.   gets(response);
  134.   if (response[0] == '\0')
  135.     return 0;
  136.   return response;
  137. }
  138.  
  139. typedef void (*PerFunc)(void *address_of_field, char *buffer);
  140.  
  141. void str_v2s(void *addr, char *buf)
  142. {
  143.   if (*(char *)addr == 0)
  144.     strcpy(buf, "\"\"");
  145.   else
  146.   {
  147.     strncpy(buf, (char *)addr, 14);
  148.     buf[14] = 0;
  149.   }
  150. }
  151.  
  152. void str_s2v(void *addr, char *buf)
  153. {
  154.   if (strcmp(buf, "\"\"") == 0)
  155.     *(char *)addr = 0;
  156.   else
  157.   {
  158.     strncpy((char *)addr, buf, 14);
  159.     ((char *)addr)[14] = 0;
  160.   }
  161. }
  162.  
  163. void bool_v2s(void *addr, char *buf)
  164. {
  165.   if (*(word8 *)addr)
  166.     strcpy(buf, "yes");
  167.   else
  168.     strcpy(buf, "no");
  169. }
  170.  
  171. void bool_s2v(void *addr, char *buf)
  172. {
  173.   switch (buf[0])
  174.   {
  175.     case 'y':
  176.     case 'Y':
  177.     case '1':
  178.     case 't':
  179.     case 'T':
  180.       *(char *)addr = 1;
  181.       break;
  182.     case 'n':
  183.     case 'N':
  184.     case '0':
  185.     case 'f':
  186.     case 'F':
  187.       *(char *)addr = 0;
  188.       break;
  189.   }
  190. }
  191.  
  192. void ver_v2s(void *addr, char *buf)
  193. {
  194.   char *field = (char *)(addr);
  195.   char *rtype = "unknown";
  196.   char *fmt = "%d.%d.%s%d";
  197.   switch (field[1])
  198.   {
  199.     case 'a':
  200.       rtype = "alpha";
  201.       break;
  202.     case 'b':
  203.       rtype = "beta";
  204.       break;
  205.     case 'f':
  206.       fmt = "%d.%d";
  207.       break;
  208.     case 'm':
  209.       rtype = "maint";
  210.       break;
  211.   }
  212.   sprintf(buf, fmt, field[3], field[2], rtype, field[0]);
  213. }
  214.  
  215. void ver_s2v(void *addr, char *buf)
  216. {
  217.   char *field = (char *)(addr);
  218.   int major = 0;
  219.   int minor = 0;
  220.   char rtype;
  221.   int release = 0;
  222.   char rstr[100];
  223.   rstr[0] = 'f';
  224.   sscanf(buf, "%d.%d.%[^0-9]%d", &major, &minor, &rstr, &release);
  225.   rtype = rstr[0];
  226.   field[3] = major;
  227.   field[2] = minor;
  228.   field[1] = rtype;
  229.   field[0] = release;
  230. }
  231.  
  232. void num_v2s(void *addr, char *buf)
  233. {
  234.   word32 v = *(word32 *)addr;
  235.   sprintf(buf, "%#lx (%dk)", v, v / 1024L);
  236. }
  237.  
  238. void num_s2v(void *addr, char *buf)
  239. {
  240.   word32 r = 0;
  241.   char s = 0;
  242.   sscanf(buf, "%i%c", &r, &s);
  243.   switch (s)
  244.   {
  245.     case 'k':
  246.     case 'K':
  247.       r *= 1024L;
  248.       break;
  249.     case 'm':
  250.     case 'M':
  251.       r *= 1048576L;
  252.       break;
  253.   }
  254.   *(word32 *)addr = r;
  255. }
  256.  
  257. struct {
  258.   char *short_name;
  259.   char *long_name;
  260.   void *addr_of_field;
  261.   PerFunc val2string;
  262.   PerFunc string2val;
  263. } per_field[] = {
  264.   { "extender",
  265.     "Name of program to run as the extender (max 13 chars)",
  266.     stub_info.go32,
  267.     str_v2s, str_s2v
  268.   },
  269.   { "version",
  270.     "Version of GO32 required to run this program",
  271.     stub_info.required_go32_version,
  272.     ver_v2s, ver_s2v
  273.   },
  274.   {
  275.     "minstack",
  276.     "Minimum amount of stack space (bytes/K/M)",
  277.     (void *)(&stub_info.min_stack),
  278.     num_v2s, num_s2v
  279.   },
  280.   {
  281.     "keepmem",
  282.     "Maximum amount of virtual memory to keep when spawning",
  283.     (void *)(&stub_info.max_keep_on_spawn),
  284.     num_v2s, num_s2v
  285.   },
  286.   {
  287.     "runfile",
  288.     "Base name of file to actually run (max 13 chars, \"\"=self)",
  289.     (void *)(&stub_info.actual_file_to_run),
  290.     str_v2s, str_s2v
  291.   },
  292.   {
  293.     "globbing",
  294.     "Enable command-line wildcard expansion (yes/no)",
  295.     (void *)(&stub_info.enable_globbing),
  296.     bool_v2s, bool_s2v,
  297.   },
  298.   {
  299.     "availmem",
  300.     "Amount of conventional memory to leave (bytes/K/M)",
  301.     (void *)(&stub_info.free_conventional_memory),
  302.     num_v2s, num_s2v
  303.   },
  304. };
  305.  
  306. #define NUM_FIELDS (sizeof(per_field) / sizeof(per_field[0]))
  307.  
  308. #define HFORMAT "%-16s %s\n"
  309.  
  310. void give_help(void)
  311. {
  312.   int i;
  313.   fprintf(stderr, "Usage: stubedit [-v] [-h] filename.exe [field=value . . . ]\n");
  314.   fprintf(stderr, "-h = give help   -v = view info  field=value means set w/o prompt\n");
  315.   fprintf(stderr, HFORMAT, "-field-", "-description-");
  316.  
  317.   for (i=0; i < NUM_FIELDS; i++)
  318.     fprintf(stderr, HFORMAT, per_field[i].short_name, per_field[i].long_name);
  319.   exit(1);
  320. }
  321.  
  322. main(int argc, char **argv)
  323. {
  324.   int view_only = 0;
  325.   int i;
  326.   int need_to_save;
  327.  
  328.   if (argc > 1 && strcmp(argv[1], "-h") == 0)
  329.     give_help();
  330.  
  331.   if (argc > 1 && strcmp(argv[1], "-v") == 0)
  332.   {
  333.     view_only = 1;
  334.     argc--;
  335.     argv++;
  336.   }
  337.  
  338.   if (argc < 2)
  339.     give_help();
  340.  
  341.   find_info(argv[1]);
  342.  
  343.   if (view_only)
  344.   {
  345.     char buf[100];
  346.     fprintf(stderr, HFORMAT, "-value-", "-field description-");
  347.     for (i=0; i<NUM_FIELDS; i++)
  348.     {
  349.       if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length)
  350.       {
  351.         per_field[i].val2string(per_field[i].addr_of_field, buf);
  352.         fprintf(stderr, HFORMAT, buf, per_field[i].long_name);
  353.       }
  354.     }
  355.     exit(0);
  356.   }
  357.  
  358.   if (argc > 2)
  359.   {
  360.     int f, got, got_any = 0;
  361.     char fname[100], fval[100];
  362.     for (i=2; i < argc; i++)
  363.     {
  364.       fname[0] = 0;
  365.       fval[0] = 0;
  366.       sscanf(argv[i], "%[^=]=%s", fname, fval);
  367.       got = 0;
  368.       for (f=0; f<NUM_FIELDS; f++)
  369.       {
  370.         if (strcmp(per_field[f].short_name, fname) == 0)
  371.         {
  372.           got = 1;
  373.           got_any = 1;
  374.           if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length)
  375.           {
  376.             per_field[f].string2val(per_field[f].addr_of_field, fval);
  377.           }
  378.           else
  379.             fprintf(stderr, "Warning: This stub does not support field %s\n", fname);
  380.         }
  381.       }
  382.       if (!got)
  383.       {
  384.         fprintf(stderr, "Error: %s is not a valid field name.\n", fname);
  385.         give_help();
  386.       }
  387.     }
  388.     if (got_any)
  389.       store_info(argv[1]);
  390.     return 0;
  391.   }
  392.  
  393.   need_to_save = 0;
  394.   for (i=0; i<NUM_FIELDS; i++)
  395.   {
  396.     char buf[100], *resp;
  397.     if ((int)(per_field[i].addr_of_field) - (int)(&stub_info) < stub_info.struct_length)
  398.     {
  399.       per_field[i].val2string(per_field[i].addr_of_field, buf);
  400.       if ((resp = pose_question(per_field[i].long_name, buf)) != 0)
  401.       {
  402.         per_field[i].string2val(per_field[i].addr_of_field, resp);
  403.         need_to_save = 1;
  404.       }
  405.     }
  406.   }
  407.   if (need_to_save)
  408.     store_info(argv[1]);
  409.  
  410.   return 0;
  411. }
  412.